package top.datacluster.basic.algorithm.leetcode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
 *
 * Note:
 *
 * The solution set must not contain duplicate triplets.
 *
 * Example:
 *
 * Given array nums = [-1, 0, 1, 2, -1, -4],
 *
 * A solution set is:
 * [
 *   [-1, 0, 1],
 *   [-1, -1, 2]
 * ]
 */
public class The3Sum {

    public static void main(String[] args) {
        int[] test = new int[]{-1, 0, 1, 2, -1, -4};
        List<List<Integer>> result = threeSum(test);
        for (List<Integer> l : result){
            System.out.println(l.get(0) + "," + l.get(1) + "," + l.get(2));
        }
    }

    public static List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        int index = 0;
        boolean haveZero = false;
        for (int i = 0; i < nums.length; i++){
            if (nums[i] == 0){
                haveZero = true;
            }
            if (nums[i] > 0){
                index = i;
                break;
            }
        }
        List<List<Integer>> result = new ArrayList<List<Integer>>();
        for (int i = 0; i < index; i++){
            int j = index;
            int k = nums.length - 1;
            List<Integer> midle = new ArrayList<Integer>();
            while (j <= k){

                if (nums[k] == Math.abs(nums[i]) && haveZero){
                    midle.add(0);
                    midle.add(nums[i]);
                    midle.add(nums[k]);
                    result.add(midle);
                    k--;

                }else if (nums[k] >= Math.abs(nums[i]) || nums[k] + nums[j] + nums[i] > 0){
                    k--;

                }else if (nums[j] + nums[k] + nums[i] == 0 && (j != k)){
                    midle.add(nums[j]);
                    midle.add(nums[i]);
                    midle.add(nums[k]);
                    result.add(midle);
                    j++;
                }else if (nums[k] + nums[j] + nums[i] < 0){
                    j++;
                }else{
                    j++;
                }
            }
        }
        return result;
    }
}
